package com.tbit.main.controller;

import cn.hutool.core.collection.CollUtil;
import com.tbit.main.common.JsonResult;
import com.tbit.main.constant.SysConstant;
import com.tbit.main.constant.SystemData;
import com.tbit.main.exception.BaseException;
import com.tbit.main.h2.pojo.ParkPoint;
import com.tbit.main.pojo.*;
import com.tbit.main.remote.rpc.UQHttpClient;
import com.tbit.main.service.*;
import com.tbit.main.util.Assert;
import com.tbit.main.util.GeoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 智能
 *
 * @author LMY
 * @create 2021-01-15 11:56
 */
@RestController
@RequestMapping("/smart")
public class SmartController {

    @Autowired
    private SmartPowerService smartPowerService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private HotIntelligentSiteService hotIntelligentSiteService;
    @Autowired
    private CalibrateService calibrateService;
    @Autowired
    private LessIntelligentSiteService lessIntelligentSiteService;
    @Autowired
    private AccountConfigService accountConfigService;
    @Autowired
    private MachineManagerService machineManagerService;
    @Autowired
    private ParkPointService parkPointService;
    @Autowired
    private GeoreGionService georeGionService;

    /**
     * 调度订单
     *
     * @param token
     * @param accountId
     * @param startTime
     * @param endTime
     * @return
     */
    @RequestMapping("/dispatchRideLog")
    public JsonResult dispatchRideLog(String token, Integer accountId, String startTime, String endTime) {

        if (SystemData.smartFlag) {
            Assert.notNull(accountId, "AccountUser.agentId.notNull");
            Assert.notNull(startTime, "System.startTime.notNull");
            Assert.notNull(endTime, "System.endTime.notNull");
            //查询预估
            List<DispatchRideLog> dispatchRideLogs = UQHttpClient.dispatchRideLog(accountId, startTime, endTime);
            return JsonResult.succ(dispatchRideLogs);
        } else {
            throw new BaseException("System.nonsupport");
        }

    }

    /**
     * 智能调度
     *
     * @return
     */
    @RequestMapping("/dispatch")
    public JsonResult dispatch(String token, Integer accountId, Double lo, Double la, Integer radius, Integer hour, Integer mapType,
                               @RequestParam(value = "regionId", required = false) List<Integer> regionId) {

        AccountUser accountUser = tokenService.getAccount(token);
        if (SystemData.smartFlag) {
            Assert.notNull(hour, "AccountEvent.control.accountEventTime.notNull");
            Assert.notNull(lo, "System.lon.notNull");
            Assert.notNull(la, "System.lat.notNull");
            Assert.notNull(accountId, "AccountUser.agentId.notNull");
            Assert.notNull(radius, "Distance.not.null");
            Assert.notNull(hour, "AccountEvent.control.accountEventTime.notNull");
            //查询预估
            List<SmartDispatch> smartDispatches = UQHttpClient.dispatch(accountId, lo, la, radius, hour, mapType);

            if (smartDispatches != null && smartDispatches.size() > 0) {

                /**站点信息*/
                List<ParkPoint> parkPointList = parkPointService.getByRegionIds(accountId, accountUser.getAccountUserId(), regionId);

                List<Integer> parkPoint = parkPointList.stream().map(ParkPoint::getParkPointId).collect(Collectors.toList());

                /** 校准 */
                calibrateService.celibrateParkPoint(parkPointList, mapType);

                Map<Integer, ParkPoint> parkPointMap = new HashMap<>();
                for (ParkPoint pointPoint : parkPointList) {
                    parkPointMap.put(pointPoint.getParkPointId(), pointPoint);
                }

                /**站点车辆*/
                List<ParkPointMachineCount> parkPointMachineCounts = parkPointService.groupByParkPoints(parkPoint);
                Map<Integer, Integer> parkPointMachineMap = new HashMap<>();
                for (ParkPointMachineCount parkPointMachineCount : parkPointMachineCounts) {
                    parkPointMachineMap.put(parkPointMachineCount.getParkPointId(), parkPointMachineCount.getMachineCount());
                }

                Iterator<SmartDispatch> iterator = smartDispatches.iterator();
                while (iterator.hasNext()) {
                    if (!parkPointMap.containsKey(iterator.next().getParkPointId())) {
                        iterator.remove();
                    }
                }

                for (SmartDispatch smartDispatch : smartDispatches) {
                    smartDispatch.setParkPointName(parkPointMap.get(smartDispatch.getParkPointId()).getName());
                    if (parkPointMachineMap.containsKey(smartDispatch.getParkPointId())) {
                        smartDispatch.setBikeCount(parkPointMachineMap.get(smartDispatch.getParkPointId()));
                    } else {
                        smartDispatch.setBikeCount(0);
                    }

                    /**点到站站点中心距离*/
                    Point point = new Point(lo, la);
                    Point pointL = new Point(parkPointMap.get(smartDispatch.getParkPointId()).getLo(), parkPointMap.get(smartDispatch.getParkPointId()).getLa());
                    smartDispatch.setDistance(GeoUtil.getDistance(point, pointL));

                    smartDispatch.setLonC((parkPointMap.get(smartDispatch.getParkPointId()).getLoC()));
                    smartDispatch.setLatC((parkPointMap.get(smartDispatch.getParkPointId()).getLaC()));
                }
            }

            return JsonResult.succ(smartDispatches);
        } else {
            throw new BaseException("System.nonsupport");
        }
    }

    /**
     * 查询热门站点
     *
     * @param token
     * @param accountId
     * @param mapType
     * @return
     */
    @RequestMapping("/hostSite")
    public JsonResult hostSite(String token, Integer accountId, Integer mapType, Integer type) {
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }
        if (SystemData.smartFlag) {
            List<HotIntelligentSite> hotIntelligentSiteList = hotIntelligentSiteService.getByAccountId(accountId, type);

            /** 校准 */
            calibrateService.celibrateHotSite(hotIntelligentSiteList, mapType);
            return JsonResult.succ(hotIntelligentSiteList);
        } else {
            throw new BaseException("System.nonsupport");
        }

    }

    /**
     * 查询冷门站点
     *
     * @param token
     * @param accountId
     * @return
     */
    @RequestMapping("/lessSite")
    public JsonResult lessSite(String token, Integer accountId,
                               @RequestParam(value = "regionId", required = false) List<Integer> regionId) {

        if (SystemData.smartFlag) {
            List<LessIntelligentSite> lessIntelligentSiteList = lessIntelligentSiteService.getByAccountId(accountId, regionId);

            return JsonResult.succ(lessIntelligentSiteList);
        } else {
            throw new BaseException("System.nonsupport");
        }

    }

    /**
     * 智能换电
     *
     * @param token
     * @param accountId
     * @param mapType
     * @param points
     * @return
     */
    @RequestMapping("/powerRadius")
    public JsonResult powerRadius(String token, Integer accountId, Integer mapType, String points,
                                  @RequestParam(value = "regionId", required = false) List<Integer> regionId) {

        AccountUser accountUser = tokenService.getAccount(token);

        Assert.notNull(accountId, "AccountUser.agentId.notNull");

        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUser.getAccountUserId());
        }

        AccountConfig accountConfig = accountConfigService.getByAccountId(accountId);
        List<MachineStatus> machineStatuses = machineManagerService.getByPower(accountUser,accountId, accountConfig.getSocLimit(), mapType, regionId, null, null);

        Iterator<MachineStatus> it = machineStatuses.iterator();
        while (it.hasNext()) {
            MachineStatus x = it.next();
            if (!smartPowerService.checkInMachineStatus(x, GeoUtil.getPoints(points), 100)) {
                it.remove();
            }
        }
        return JsonResult.succ(machineStatuses);
    }

}
